當專案規模越來越大,會需要許多子目錄以便管理程式碼,通常每一個子目錄都要有自己的CMakeLists.txt負責處理該目錄的檔案,因此本篇會介紹如建立與管理子目錄。
定義:將子目錄加入編譯
add_subdirectory(source_dir [binary_dir])
source_dir : 子目錄路徑(相對於目前這個CMakeLists.txt)
binary_dir : binary輸出路徑(會影響CMAKE_CURRENT_BINARY_DIR變數)
定義:編譯出的二進制檔案所在位置
在add_subdirectory(filename [ ])的 binary_dir 沒有指定的情況下為$(PROJECT_BINARY_DIR)/filename
定義:現在的 CMakeListx.txt 檔案原始碼所在位置。
定義:將原始碼編譯成不同格式的二進制檔,之後會詳細介紹,今天會將原始碼編譯成Object檔(.o file)。
add_library(<name> OBJECT <source>)
name : 二進制檔名稱
source : 原始碼檔名
定義:指定二進制檔案要包含的include目錄
target_include_directories(<target> <INTERFACE|PUBLIC|PRIVATE> [items])
target : 二進制檔案要名稱
<INTERFACE|PUBLIC|PRIVATE> : 選擇將include路徑是否向上傳遞,這個概念未來會講解。
items : include 的標頭檔路徑
定義:將執行檔與二進制檔鍊結起來
target_link_libraries(<target> ... <item>...)
target : 執行檔名稱
item : 要與執行檔鍊結的二進制檔案名稱
$ git clone https://github.com/m11112089/2023_iT_CMake.git
$ cd ~/2023_iT_CMake/Day9/1
目錄結構為
├── build
├── CMakeLists.txt
├── MathFunctions
│ ├── CMakeLists.txt
│ ├── include
│ │ └── mysqrt.h
│ └── src
│ └── mysqrt.cpp
└── src
└── main.cpp
頂層 CMakeLists.txt 需要將MathFunctions加入下層目錄中,執行到這行時就會跳到MathFunctions/CMakeLists.txt 繼續編譯 。
add_subdirectory(MathFunctions)
先將原始碼編譯成OBJECT檔,再將MathFunctions/include資料夾內的標頭檔使用PUBLIC的方式向上傳遞給main,否則main無法使用mysqrt的include目錄,造成編譯錯誤。
add_library(mysqrt OBJECT src/mysqrt.cpp)
# 將mysqrt.cpp編譯成名為mysqrt的object檔案
target_include_directories(mysqrt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
# 將 ${CMAKE_CURRENT_SOURCE_DIR}/include 目錄加入 mysqrt 的 include 目錄,並且使用PUBLIC的方式向上傳遞給main,
# 否則main無法使用mysqrt的include目錄,造成編譯錯誤
接下來查看CMake_CURRENT_SOURCE_DIR和CMake_CURRENT_BINARY_DIR的值
message(STATUS "CMake_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "CMake_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}")
# 查看 CMake_CURRENT_SOURCE_DIR 和 CMake_CURRENT_BINARY_DIR 的值
因為沒有在add_subdirectory() 函式中指定二進制檔案輸出位置,
$ {CMAKE_CURRENT_BINARY_DIR} 的值預設會是 $ (PROJECT_BINARY_DIR)/filename 。
而我們在 build 資料夾中編譯,因此編譯過程中所產生的檔案路徑 $ (PROJECT_BINARY_DIR) 會等於build資料夾,因此 $ {CMAKE_CURRENT_BINARY_DIR} 值也就等於 ~/2023_iT_CMake/Day9/1/build/MathFunctions
kai@esoc:~/2023_iT_CMake/Day9/1/build$ cmake ..
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- MathFunctions CMake_CURRENT_SOURCE_DIR: /home/kai/2023_iT_CMake/Day9/1/MathFunctions
-- MathFunctions CMake_CURRENT_BINARY_DIR: /home/kai/2023_iT_CMake/Day9/1/build/MathFunctions
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kai/2023_iT_CMake/Day9/1/build
在將MathFunctions / src / mysqrt.cpp 編譯成二進制檔後,將執行檔與其鍊結。
target_link_libraries(main mysqrt)
# 將main與mysqrt鍊結
$ cd ~/2023_iT_CMake/Day9/2
目錄結構為
├── build
├── CMakeLists.txt
├── MathFunctions
│ └── MathFunctions
│ ├── CMakeLists.txt
│ ├── include
│ │ └── mysqrt.h
│ └── src
│ └── mysqrt.cpp
└── src
└── main.cpp
頂層 CMakeLists.txt 需要將MathFunctions/MathFunctions加入下層目錄中
add_subdirectory(MathFunctions/MathFunctions)
$ cmake ..
$ make
kai@esoc:~/2023_iT_CMake/Day9/2/build$ cmake ..
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- MathFunctions CMake_CURRENT_SOURCE_DIR: /home/kai/2023_iT_CMake/Day9/2/MathFunctions/MathFunctions
-- MathFunctions CMake_CURRENT_BINARY_DIR: /home/kai/2023_iT_CMake/Day9/2/build/MathFunctions/MathFunctions
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kai/2023_iT_CMake/Day9/2/build
kai@esoc:~/2023_iT_CMake/Day9/2/build$ make
[ 33%] Building CXX object MathFunctions/MathFunctions/CMakeFiles/mysqrt.dir/src/mysqrt.cpp.o
[ 33%] Built target mysqrt
[ 66%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
$ cd ~/2023_iT_CMake/Day9/3
├── build
├── CMakeLists.txt <-- 這裡有一個
├── MathFunctions
│ ├── CMakeLists.txt <-- 這裡也有一個
│ └── MathFunctions
│ ├── CMakeLists.txt <-- 這裡還有一個
│ ├── include
│ │ └── mysqrt.h
│ └── src
│ └── mysqrt.cpp
└── src
└── main.cpp
但是第二種情況比較少見,通常每一層目錄都會由CMakeLists.txt進行管理。
頂層 Day9 / CMakeLists.txt
add_subdirectory(MathFunctions)
下一層 Day9 / MathFunctions / CMakeLists.txt
add_subdirectory(MathFunctions)
kai@esoc:~/2023_iT_CMake/Day9/3/build$ cmake ..
-- The CXX compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- MathFunctions CMake_CURRENT_SOURCE_DIR: /home/kai/2023_iT_CMake/Day9/3/MathFunctions/MathFunctions
-- MathFunctions CMake_CURRENT_BINARY_DIR: /home/kai/2023_iT_CMake/Day9/3/build/MathFunctions/MathFunctions
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kai/2023_iT_CMake/Day9/3/build
kai@esoc:~/2023_iT_CMake/Day9/3/build$ make
[ 33%] Building CXX object MathFunctions/MathFunctions/CMakeFiles/mysqrt.dir/src/mysqrt.cpp.o
[ 33%] Built target mysqrt
[ 66%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
還挺像套娃的